package com.neusoft.neuiotms.dcam.workflow.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;

import org.apache.cxf.common.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.activiti.dto.ProcessInstanceDTO;
import com.neusoft.bizcore.activiti.service.ProcessInstanceService;
import com.neusoft.bizcore.activiti.service.WorkOrderService;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcam.constant.DCAMConsts;
import com.neusoft.neuiotms.dcam.fixed.converter.AssetConverter;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetLifeCycleDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.WarehouseRecordDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Asset;
import com.neusoft.neuiotms.dcam.fixed.model.GoodsFile;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetRepository;
import com.neusoft.neuiotms.dcam.fixed.repository.GoodsFileRepository;
import com.neusoft.neuiotms.dcam.fixed.service.AssetLifeCycleService;
import com.neusoft.neuiotms.dcam.fixed.service.AssetService;
import com.neusoft.neuiotms.dcam.fixed.service.StorehouseService;
import com.neusoft.neuiotms.dcam.fixed.service.WarehouseRecordService;
import com.neusoft.neuiotms.dcam.workflow.converter.ITSMApproveConverter;
import com.neusoft.neuiotms.dcam.workflow.converter.LingyongConfrimKJConverter;
import com.neusoft.neuiotms.dcam.workflow.converter.LingyongKJConverter;
import com.neusoft.neuiotms.dcam.workflow.dto.ITSMApproveDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.LingyongConfrimKJDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.LingyongKJDTO;
import com.neusoft.neuiotms.dcam.workflow.model.ITSMApprove;
import com.neusoft.neuiotms.dcam.workflow.model.LingyongConfrimKJ;
import com.neusoft.neuiotms.dcam.workflow.model.LingyongItemKJ;
import com.neusoft.neuiotms.dcam.workflow.model.LingyongKJ;
import com.neusoft.neuiotms.dcam.workflow.model.WorkOrderDeposit;
import com.neusoft.neuiotms.dcam.workflow.repository.ITSMApproveRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.LingyongConfrimKJRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.LingyongKJRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.WorkOrderDepositRepository;
import com.neusoft.neuiotms.dcam.workflow.service.LingyongKJService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import io.micrometer.core.instrument.util.StringUtils;

@Service
public class LingyongKJServiceImpl implements LingyongKJService {

    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private LingyongKJRepository lingyongKJRepository;
    @Autowired
    private LingyongKJConverter lingyongKJConverter;
    @Autowired
    private ITSMApproveRepository approveRepository;
    @Autowired
    private ITSMApproveConverter approveConverter;
    @Autowired
    private LingyongConfrimKJRepository lingyongConfrimKJRepository;
    @Autowired
    private LingyongConfrimKJConverter lingyongConfrimKJConverter;
    @Autowired
    private AuthMicroService authMicroService;
    @Autowired
    private AssetRepository assetRepository;
    @Autowired
    private AssetLifeCycleService assetLifeCycleService;
    @Autowired
    private AssetConverter assetConverter;
    @Autowired
    private AssetService assetService;
    @Autowired
    private GoodsFileRepository goodsFileRepository;
    @Autowired
    private WarehouseRecordService warehouseRecordService;
    @Autowired
    private StorehouseService storehouseService;
    @Autowired
    private WorkOrderDepositRepository workOrderDepositRepository;

    @Override
    @Transactional
    public LingyongKJDTO create(final LingyongKJDTO dto, final UserBean user) {

        final String taskId = dto.getTaskId();
        final ProcessInstanceDTO instance = this.workOrderService.submit(dto.getTitle(),
                DCAMConsts.PROCESSS_LINGYONG_KJ_KEY, dto.getWorkOrderNum(), user);
        dto.setTaskId(instance.getTaskId());
        dto.setWorkOrderNum(instance.getWorkorderNum());
        dto.setCreateUser(user.getUsername());
        dto.setCreateUserName(user.getName());
        final List<String> orgs = user.getOrgs();
        if (orgs != null) {
            dto.setOrgCode(orgs.get(0));
            dto.setOrgName(this.authMicroService.orgInfoByCode(orgs.get(0)).getData().get("name").toString());
        }

        // 查询当前workOrderNum和TaskId下是否存在记录
        final LingyongKJ oldModel = this.lingyongKJRepository.findByWorkOrderNumAndTaskId(
                dto.getWorkOrderNum(), taskId);
        if (oldModel == null) {
            dto.setId(null);
        }

        LingyongKJ model = this.lingyongKJConverter.toModel(dto);
        model = this.lingyongKJRepository.save(model);

        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        // 固定资产和消耗品领用都推送ITSM审批，审批逻辑移到ProcessApproveServiceImpl中实现
        // if ("1".equals(dto.getCategories())) {
        //        try {
        //            // 对接ITSM
        //            final List<WorkflowBean.AssetBean> assetList = Lists.newArrayList();
        //            for (final LingyongItemKJDTO item : dto.getRecipientRequires()) {
        //                final WorkflowBean.AssetBean assetBean = WorkflowBean.AssetBean.builder()
        //                        .assetClassID(item.getSmallTypeCode())
        //                        .assetModel(item.getSpecifications())
        //                        .assetUnit("未知")
        //                        .assetPrice(0)
        //                        .assetNumber(item.getQuantity())
        //                        .assetName(item.getSmallTypeName())
        //                        .assetType("1")
        //                        .assetSign("未知")
        //                        .build();
        //                assetList.add(assetBean);
        //            }
        //
        //            final WorkflowBean workflowBean = WorkflowBean.builder()
        //                    .workNum(dto.getWorkOrderNum())
        //                    .workName("设备领用")
        //                    .workType("20")
        //                    .workContent("设备领用申请")
        //                    .applyUser(user.getUsername())
        //                    .assetList(assetList)
        //                    .build();
        //
        //            this.itsmService.pushItsm(workflowBean);
        //        } catch (final Exception e) {
        //            LingyongKJServiceImpl.log.error("设备领用流程推送ITSM时发生错误", e);
        //        }
        // }

        final LingyongKJDTO result = this.lingyongKJConverter.toDTO(model);

        return result;
    }

    @Override
    public LingyongKJDTO detail(final String workOrderNum, final String taskId, final UserBean user) {
        LingyongKJ model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.lingyongKJRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new LingyongKJDTO();
                    } else {
                        model = this.lingyongKJRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                model = this.lingyongKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.lingyongKJConverter.toDTO(model);
    }

    @Override
    @Transactional
    public ITSMApproveDTO itsmCreate(final ITSMApproveDTO dto, final UserBean user) {
        final ITSMApprove model = this.approveConverter.toModel(dto);
        this.approveRepository.save(model);

        this.processInstanceService.setGlobalVariable(dto.getTaskId(), DCAMConsts.PROCESSS_LINGYONG_KJ_APPROVE_RESULT,
                dto.getResult());
        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        return this.approveConverter.toDTO(model);
    }

    @Override
    public ITSMApproveDTO itsmDetails(final String workOrderNum, final String taskId, final UserBean user) {
        ITSMApprove model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new ITSMApproveDTO();
                    } else {
                        model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                final List<ITSMApprove> LingyongKJs =
                        this.approveRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
                if ((LingyongKJs != null) && (LingyongKJs.size() > 0)) {
                    model = LingyongKJs.get(0);
                }
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.approveConverter.toDTO(model);
    }

    @Transactional
    @Override
    public List<LingyongConfrimKJDTO> confrimCreate(final List<LingyongConfrimKJDTO> dto, final UserBean user) {

        final List<LingyongConfrimKJ> models = this.lingyongConfrimKJConverter.toListModel(dto);
        this.lingyongConfrimKJRepository.saveAll(models);

        // 完成当前节点
        this.processInstanceService.complete(dto.get(0).getWorkOrderNum(), dto.get(0).getTaskId(), user);
        //        // 枷锁资产信息
        //        this.assetService.updateLocked(dto.stream().map(l -> l.getCode()).distinct().collect(Collectors.toList()),
        //                true);
        final LingyongKJ lingyong =
                this.lingyongKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(dto.get(0).getWorkOrderNum());
        this.lingyongCompleteUpdate(dto, lingyong.getOrgCode(), lingyong.getOrgName(), lingyong.getCategories());
        this.saveTemporary(dto.get(0).getWorkOrderNum());
        return this.lingyongConfrimKJConverter.toListDTO(models);

    }

    @Override
    public LingyongKJDTO confrimDetail(final String workOrderNum, final String taskId, final UserBean user) {
        LingyongKJDTO dto = new LingyongKJDTO();
        // 获取条件
        final List<LingyongKJ> lingyongKJs =
                this.lingyongKJRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
        if ((lingyongKJs != null) && (lingyongKJs.size() > 0)) {
            dto = this.lingyongKJConverter.toDTO(lingyongKJs.get(0));
        }

        List<LingyongConfrimKJ> model = new ArrayList<>();
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.lingyongConfrimKJRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                dto.setLingyong(this.lingyongConfrimKJConverter.toListDTO(model));
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return dto;
    }

    @Transactional
    @Override
    public List<LingyongConfrimKJDTO> distributeCreate(final List<LingyongConfrimKJDTO> dto, final UserBean user) {

        final LingyongKJ lingyong =
                this.lingyongKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(dto.get(0).getWorkOrderNum());

        final List<LingyongConfrimKJ> models = dto.stream().map(l -> {
            l.setManagementOrgCode(lingyong.getOrgCode());
            l.setManagementOrgName(lingyong.getOrgName());
            final LingyongConfrimKJ model = this.lingyongConfrimKJRepository.getOne(l.getId());
            model.setManagementUserCode(l.getManagementUserCode());
            model.setManagementUserName(l.getManagementUserName());
            model.setLingyongLocation(l.getLingyongLocation());
            model.setLingyongLocationName(l.getLingyongLocationName());
            return model;
        }).collect(Collectors.toList());

        this.lingyongConfrimKJRepository.saveAll(models);

        this.processInstanceService.complete(dto.get(0).getWorkOrderNum(), dto.get(0).getTaskId(), user);

        //        this.lingyongCompleteUpdate(dto);
        return this.lingyongConfrimKJConverter.toListDTO(models);
    }

    @Override
    public LingyongKJDTO distributeDetail(final String workOrderNum, final String taskId,
            final UserBean user) {

        LingyongKJDTO dto = new LingyongKJDTO();
        // 获取条件
        final List<LingyongKJ> lingyongKJs =
                this.lingyongKJRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
        if ((lingyongKJs != null) && (lingyongKJs.size() > 0)) {
            dto = this.lingyongKJConverter.toDTO(lingyongKJs.get(0));
        }

        List<LingyongConfrimKJ> model = new ArrayList<>();
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.lingyongConfrimKJRepository.findByWorkOrderNum(workOrderNum);
                dto.setLingyong(this.lingyongConfrimKJConverter.toListDTO(model));
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return dto;
    }

    private void lingyongCompleteUpdate(final List<LingyongConfrimKJDTO> dto, final String orgCode,
            final String orgName, final String categories) {

        final List<AssetLifeCycleDTO> lifeList = new ArrayList<>();
        final List<WarehouseRecordDTO> records = new ArrayList<>();

        switch (categories) {
        case "3":
            dto.stream().map(l -> {
                final List<Asset> list = new ArrayList<>();
                final Asset model = this.assetRepository.findByCode(l.getCode());
                model.setAmount(model.getAmount() - l.getLingyongQuantity());
                model.setLocked(false);
                list.add(model);

                // 判断是否为库房
                if (this.storehouseService.LocationIsStorehouse(model.getLocation())) {
                    records.add(WarehouseRecordDTO.builder()
                            .name(model.getName())
                            .specifications(model.getSpecifications())
                            .brand(model.getBrand())
                            .smallTypeName(model.getSmallTypeName())
                            .smallTypeCode(model.getSmallTypeName()).contractNo(model.getContractNo())
                            .contractName(model.getContractName()).amount(l.getLingyongQuantity())
                            .location(model.getLocation())
                            .locationName(model.getLocationName()).type("2").build());
                }

                final Asset xh =
                        this.assetRepository
                                .findTopBySmallTypeCodeAndSpecificationsAndManagementOrgCodeOrderByCreateTimeDesc(
                                        l.getSmallTypeCode(), l.getSpecifications(), orgCode);
                if (xh != null) {
                    xh.setAmount(xh.getAmount() + l.getLingyongQuantity());
                    list.add(xh);

                    // 生命周期
                    lifeList.add(AssetLifeCycleDTO.builder().code(xh.getCode())
                            .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_JILU)
                            .content("数量为" + l.getLingyongQuantity() + "的" + l.getSmallTypeName() + "已领用")
                            .workNum(dto.get(0).getWorkOrderNum()).build());
                } else {
                    AssetDTO assetDTO = this.assetConverter.toDTO(model);
                    assetDTO.setId(null);
                    assetDTO.setAmount(l.getLingyongQuantity());
                    assetDTO.setManagementOrgName(orgName);
                    assetDTO.setManagementOrgCode(orgCode);
                    assetDTO.setAmount(0);
                    assetDTO = this.assetService.create(assetDTO, null, null);

                    // 生命周期
                    lifeList.add(AssetLifeCycleDTO.builder().code(assetDTO.getCode())
                            .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_JILU)
                            .content("数量为" + l.getLingyongQuantity() + "的" + l.getSmallTypeName() + "已领用")
                            .workNum(dto.get(0).getWorkOrderNum()).build());
                }
                // 生命周期
                lifeList.add(AssetLifeCycleDTO.builder().code(l.getCode())
                        .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_JILU)
                        .content("数量为" + l.getLingyongQuantity() + "的" + l.getSmallTypeName() + "已发给"
                                + orgName + "部门")
                        .workNum(dto.get(0).getWorkOrderNum()).build());
                //                this.assetRepository.saveAll(list);
                return model;
            }).collect(Collectors.toList());

            break;

        case "4":
            final List<GoodsFile> goodsFile = dto.stream().map(l -> {
                final GoodsFile model = this.goodsFileRepository.findByCode(l.getCode());
                model.setManagementOrgCode(orgCode);
                model.setManagementOrgName(orgName);

                // 生命周期
                lifeList.add(AssetLifeCycleDTO.builder().code(model.getCode())
                        .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_LINGYONG)
                        .content(model.getName() + "已被" + orgName + "部门领用").workNum(dto.get(0).getWorkOrderNum())
                        .build());

                return model;
            }).collect(Collectors.toList());

            if ((goodsFile != null) && (goodsFile.size() > 0)) {
                this.goodsFileRepository.saveAll(goodsFile);
            }

            break;
        default:
            final LingyongKJ lingyong =
                    this.lingyongKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(dto.get(0).getWorkOrderNum());

            final List<Asset> assets = dto.stream().map(l -> {
                final Asset model = this.assetRepository.findByCode(l.getCode());
                model.setManagementUserCode(lingyong.getCreateUser());
                model.setManagementUserName(lingyong.getCreateUserName());
                model.setManagementOrgCode(orgCode);
                model.setManagementOrgName(orgName);
                model.setLocation(null);
                model.setLocationName(null);
                model.setLocked(false);
                // 如果分配人员的情况下资产为再用否则为闲置
                model.setStatus(DCAMConsts.ASSET_STATUS_USED);

                // 生命周期
                lifeList.add(AssetLifeCycleDTO.builder().code(model.getCode())
                        .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_LINGYONG)
                        .content(model.getName() + "已被" + orgName + "部门领用").workNum(dto.get(0).getWorkOrderNum())
                        .build());

                return model;
            }).collect(Collectors.toList());

            if ((assets != null) && (assets.size() > 0)) {
                this.assetRepository.saveAll(assets);
            }

            break;
        }

        if (records.size() > 0) {
            this.warehouseRecordService.batchCreate(records);
        }

        if (lifeList.size() > 0) {
            this.assetLifeCycleService.batchCreate(lifeList);
        }
    }

    private List<WorkOrderDeposit> saveTemporary(final String workNum) {
        final List<WorkOrderDeposit> depositList = new ArrayList<>();
        final List<LingyongKJ> lingyongs =
                this.lingyongKJRepository.findByWorkOrderNum(workNum);
        //获取已有库存的宝贝
        final Searchable searchable = new Searchable();
        searchable.put("categories", "3");
        final List<Asset> assetList = this.assetRepository.search(searchable);

        //判断申请入库的消耗品是否为空
        if (!CollectionUtils.isEmpty(lingyongs)) {
            //获取申请入库的宝贝信息
            final LingyongKJ lingyongKJ = lingyongs.get(0);
            final List<LingyongItemKJ> lingyongList = lingyongKJ.getRecipientRequires();
            lingyongList.stream().forEach(lingyong -> {
                if ("3".equals(lingyongKJ.getCategories())) {
                    //                    int i = 0;
                    for (final Asset asset : assetList) {
                        if (asset.getSmallTypeName().equals(lingyong.getSmallTypeName())) {
                            //                            i = 1;
                            final WorkOrderDeposit model = new WorkOrderDeposit();
                            model.setWorkOrderNum(workNum);
                            model.setSmallTypeCode(asset.getSmallTypeCode());
                            model.setSmallTypeName(asset.getSmallTypeName());
                            model.setQuantity(asset.getAmount());
                            depositList.add(model);
                        }
                    }
                    //                    if (i == 0) {
                    //                        final WorkOrderDeposit model = new WorkOrderDeposit();
                    //                        model.setWorkOrderNum(workNum);
                    //                        model.setQuantity(lingyong.getQuantity());
                    //                        model.setSmallTypeCode(lingyong.getSmallTypeCode());
                    //                        model.setSmallTypeName(lingyong.getSmallTypeName());
                    //                        depositList.add(model);
                    //                    }
                }
            });
            this.workOrderDepositRepository.saveAll(depositList);
        }
        return depositList;
    }

}
